package model.agent

import groovy.mock.interceptor.Demand;
import model.Model
//@CompileStatic
class Firm extends Agent {

	ArrayList<HouseHold> workers = new ArrayList<HouseHold>()

	ArrayList<HouseHold> clients = new ArrayList<HouseHold>()

	//存货上下限
	private upperIv
	private lowerIv

	private upperPrice
	private lowerPrice

	private dDm			//daily demond counter
	private dIv			//daily invertory counter
	private dMoney		//daily money counter
	private dPosi		//daily positions counter

	private fireWho = -1  //要炒掉的人的who


	def Firm(){
		[
			"mMoney",
			"mIv",
			"mPrice",
			"mWage",
			"mDm",
			"mPosi"
		].each{ this.addProperty(it) }
	}

	def initMonth(){

		//init daily vars
		dDm = 0
		dIv = mIv
		dMoney = mMoney
		dPosi = mPosi


		lowerIv = mDm * Model.LOWER_IV_FACTOR
		upperIv = mDm * Model.UPPER_IV_FACTOR


		upperPrice = getMc() * Model.UPPER_PRICE_FACTOR
		lowerPrice = getMc() * Model.LOWER_PRICE_FACTOR

		fireSomeone()

		adjustWage()

		adjustPosition()

		adjustPrice()
	}

	def getMc(){
		if(workers.size()==0) {return 0}
		return mWage

	}

	def applyFrom(HouseHold h){
		if(mWage > h.rWage && dPosi > 0){
			workers.add(h)
			dPosi -= 1

			out "${this}招聘了${h}"
			out workers
			//out workers.workingFirm
			return true
		}
		return false
	}
	def fireSomeone(){
		if (fireWho != -1){
			HouseHold w = workers.find{ HouseHold h ->
				h.who == fireWho
			}
			if (w!=null){
				//			out fireWho
				//			out workers
				w.workingFirm = null
				workers.remove(w)

				fireWho = -1
			}

			out "${this}炒了" + w

		}

		//out workers
	}

	def endMonth(){
		pay()
		dividend()

		// update monthly vars
		mDm = dDm
		mIv = dIv
		mMoney = dMoney
		mPosi = dPosi


	}

	def dividend(){
		def d = dMoney / workers.size()
		workers.each {
			it.money+=d
			dMoney -=d
		}
	}

	/**
	 * 工资调整。
	 * if 有空缺，提高工资
	 * if 过去20个月都没空缺，则减少工资
	 * @return
	 */
	private adjustWage(){
		if(mPosi > 0 ) {raiseWage()}
		else{
			ArrayList p = this.getPropertyArray("mPosi")
			if(p.size>=Model.FULL_MONTHS){
				def plast = p[-Model.FULL_MONTHS..-1]
				if(p.every(){it == 0})
				{cutWage()}
			}
		}
	}

	private raiseWage(){
		def r = Model.random() * Model.MAX_WAGE_GROWTH_RATE
		mWage = mWage*(1+r)
	}

	private cutWage(){
		def r = Model.random() * Model.MAX_WAGE_GROWTH_RATE
		mWage = mWage*(1-r)
	}

	def adjustPosition(){
		if (mIv < lowerIv){
			openPositon()
		}else if(mIv > upperIv) {
			if (dPosi>0){
				dPosi--
			}
			setFire()
		}

	}

	def openPositon(){
		dPosi = 1
		out "${this}招人！"
	}

	def setFire(){
		if(workers.size()>0){
			HouseHold w = Model.oneof(workers)
			//			out workers
			//			out w
			//out workers
			fireWho = w.who
			//out this.toString() + "要炒掉的是" + w
		}
	}

	def adjustPrice(){

//		out "mIv:"+mIv.round(3)
//		out "lowerIv:"+lowerIv.round(3)
//		out "upperIv:"+upperIv.round(3)
//		out ""
//		out "mPrice:"+mPrice.round(3)
//		out "upperPrice:"+upperPrice.round(3)
//		out "lowerPrice:"+lowerPrice.round(3)
//		out ""

		if(mIv < lowerIv && mPrice < upperPrice){

			raisePrice()
		}
		if(mIv > upperIv && mPrice > lowerPrice){
			cutPrice()
		}
	}

	def raisePrice(){
		def r = Model.random() * Model.MAX_PRICE_GROWTH_RATE
		mPrice = mPrice* (1+r)
	}

	def cutPrice(){
		def r = Model.random() * Model.MAX_PRICE_GROWTH_RATE
		mPrice = mPrice* (1-r)
	}


	def sell(q){
		dDm += q
		if (q == null) {throw new IllegalArgumentException("${Firm.toString()}.sell():购买量不能是NULL")}
		if (q <= 0) {throw new IllegalArgumentException("${Firm.toString()}.sell():购买量不能<0: $q")}

		if (q <= dIv){ //存货足够
			dIv -= q
		}else{
			q = dIv
			dIv  = 0
		}

		dMoney += (q * mPrice)
		//out "dMoney:" + dMoney
		return q
	}

	def produce() {

		dIv += Model.TECHNOLOGY * workers.size()
		//		out workers
		//		Model.totalWorkers += workers.size()

	}

	def pay(){
		if(dMoney>0){
			//out "money:" + dMoney
			def perPay = 0
			if(mWage * workers.size() <= dMoney){ //给得起
				perPay = mWage

			}else{ //给不起，则给剩余
				perPay = dMoney / workers.size()

			}

			//out this.toString() + "支付:" + perPay

			workers.each{ HouseHold h ->
				//				if(h.who==2) {
				//					out h.toString() + h.money
				//
				//				}
				h.money += perPay

				//				if(h.who==2) out h.money

			}

			dMoney -=  perPay * workers.size()
		}

	}


	def addWorker(HouseHold worker){
		workers.add(worker)
	}

	def addClient(HouseHold client){
		clients.add(client)
	}

	String toString(boolean detailed=false){
		def s = super.toString()
		if(detailed){
			s+= "\n" + "workers: " + workers.toString()
			s+= "\n" + "clients: " + clients.toString()
			s+= "\n" + prop
		}
		return s
	}

}

/*
 *
 *
 *
 *
 *
 *
 */